Récupération des données

Les scripts de création des données sont dans le dépot github notebook : http://nbviewer.ipython.org/github/philippechataignon/notebook/tree/master


In [76]:
st = pd.HDFStore('data/data.h5')
dc_clc = set(st.clc2006.index)
dc_euro = set(st.euro2014.index)
dc_ref = set(st.cog2014.index)

Vérification code commune

Toutes les communes issues de Corine Land Cover sont dans le code officiel géographique.


In [77]:
dc_clc - dc_ref


Out[77]:
set()

Toutes les communes issues des résulats électoraux ne sont pas dans le code officiel géographique. Toutefois, on peut vérifier qu'il ne s'agit que des circonscriptions des français de l'étranger (en fait non, cf ci-dessous).

Errata : suite à tweet de @vallettea et @louisdorard, il y a également les circonscriptions DOM/TOM :

if x in set(["ZA", "ZB", "ZC", "ZD", "ZS"]): #guadeloupe, martinique, guyanne, reunion, St pierre et miquelon
    return "97"
elif x in set(["ZP", "ZN"]): #polynesie, nouvelle caledonie
    return "98"
else:
    return as_string(x)

In [78]:
" ".join(sorted(dc_euro - dc_ref))


Out[78]:
'ZA101 ZA102 ZA103 ZA104 ZA105 ZA106 ZA107 ZA108 ZA109 ZA110 ZA111 ZA112 ZA113 ZA114 ZA115 ZA116 ZA117 ZA118 ZA119 ZA120 ZA121 ZA122 ZA124 ZA125 ZA126 ZA128 ZA129 ZA130 ZA131 ZA132 ZA133 ZA134 ZB201 ZB202 ZB203 ZB204 ZB205 ZB206 ZB207 ZB208 ZB209 ZB210 ZB211 ZB212 ZB213 ZB214 ZB215 ZB216 ZB217 ZB218 ZB219 ZB220 ZB221 ZB222 ZB223 ZB224 ZB225 ZB226 ZB227 ZB228 ZB229 ZB230 ZB231 ZB232 ZB233 ZB234 ZC301 ZC302 ZC303 ZC304 ZC305 ZC306 ZC307 ZC308 ZC309 ZC310 ZC311 ZC312 ZC313 ZC314 ZC352 ZC353 ZC356 ZC357 ZC358 ZC360 ZC361 ZC362 ZD401 ZD402 ZD403 ZD404 ZD405 ZD406 ZD407 ZD408 ZD409 ZD410 ZD411 ZD412 ZD413 ZD414 ZD415 ZD416 ZD417 ZD418 ZD419 ZD420 ZD421 ZD422 ZD423 ZD424 ZM501 ZM502 ZM503 ZM504 ZM505 ZM506 ZM507 ZM508 ZM509 ZM510 ZM511 ZM512 ZM513 ZM514 ZM515 ZM516 ZM517 ZN801 ZN802 ZN803 ZN804 ZN805 ZN806 ZN807 ZN808 ZN809 ZN810 ZN811 ZN812 ZN813 ZN814 ZN815 ZN816 ZN817 ZN818 ZN819 ZN820 ZN821 ZN822 ZN823 ZN824 ZN825 ZN826 ZN827 ZN828 ZN829 ZN830 ZN831 ZN832 ZN833 ZP011 ZP012 ZP013 ZP014 ZP015 ZP016 ZP017 ZP018 ZP019 ZP020 ZP021 ZP022 ZP023 ZP024 ZP025 ZP026 ZP027 ZP028 ZP029 ZP030 ZP031 ZP032 ZP033 ZP034 ZP035 ZP036 ZP037 ZP038 ZP039 ZP040 ZP041 ZP042 ZP043 ZP044 ZP045 ZP046 ZP047 ZP048 ZP049 ZP050 ZP051 ZP052 ZP053 ZP054 ZP055 ZP056 ZP057 ZP058 ZS501 ZS502 ZW001 ZX701 ZX801'

Nettoyage code commune

La gestion de la géographie adminstrative est toujours un problème à règler lorsqu'on travaille avec plusieurs sources. Ici, on part du fichier historique des communes disponible sur le site de l'INSEE, qui fournit pour chaque commune non active son pôle, par exemple la commune vers laquelle elle a fusionnée. Pur les communes actives, et contrairement à ce que fait l'INSEE, on a repris le code de la commune dans le pôle, ce qui fait que l'on peut systématiquement utiliser le passage code commune vers pôle pour ramener les informations sur une géographie actuelle.

Pour chaque table de données, dans un permier temps, on récupère l'information sur le pôle dans les tables de donnée en faisant une jointure. Puis on supprime les lignes où pole est à null. Ensuite, pole devient le nouvel index du DataFrame. On peut vérifier qu'il n'est pas unique et on le rend unique en sommant toutes les variables.


In [79]:
p = st.cog2014.pole
euro2014 = st.euro2014.join(p)
euro2014.dropna(subset=['pole'], inplace=True)
euro2014.set_index('pole', inplace=True)
euro2014.index.is_unique
euro = euro2014.groupby(euro2014.index).sum()

In [80]:
clc2006 = st.clc2006.join(p)
clc2006.dropna(subset=['pole'], inplace=True)
clc2006.set_index('pole',inplace=True)
clc2006.index.is_unique
clc = clc2006.groupby(clc2006.index).sum()

Jointure des tables de données

Maintenant que la géographie a été traitée, on peut rapprocher les données par code commune (en fait pole). On nettoie les lignes avec dans valeurs manquantes.


In [81]:
w = euro.join(clc)
w.dropna(inplace=True)
w.head()
# w.to_csv('data/etude_clc_euro.tsv', delimiter='\t')


Out[81]:
Inscrits Abstentions Votants Blancs Nuls Exprimés LEXG LUG LFG LDVG ... 411 412 421 422 423 511 512 521 522 523
pole
01001 593 312 281 17 2 262 0 37 4 8 ... 0 0 0 0 0 0 0.000000 0 0 0
01002 226 99 127 2 1 124 0 6 9 4 ... 0 0 0 0 0 0 0.000000 0 0 0
01004 8153 4825 3328 76 30 3222 30 433 197 98 ... 0 0 0 0 0 0 0.000000 0 0 0
01005 1158 669 489 20 2 467 0 51 9 16 ... 0 0 0 0 0 0 184.330686 0 0 0
01006 108 55 53 1 0 52 0 10 1 2 ... 0 0 0 0 0 0 0.000000 0 0 0

5 rows × 62 columns

Calcul des proportions

On va calculer la proportion pour les différents type de terrains dans les colonnes préfixées par p. De même, pour le vote FN, on s'intéresse au % par rapport aux exprimés.


In [82]:
import statsmodels.api as sm
clc = [u'111', u'112', u'121', u'122', u'123', u'124', u'131', u'132', u'133', u'141', 
    u'142', u'211', u'212', u'213', u'221', u'222', u'223', u'231', u'241', u'242', 
    u'243', u'244', u'311', u'312', u'313', u'321', u'322', u'323', u'324', u'331', 
    u'332', u'333', u'334', u'335', 
    u'411', u'412', u'421', u'422', u'423', u'511', u'512', u'521', u'522', u'523']

pclc = ['p' + l for l in clc]
w[pclc] = w[clc].div(w[clc].sum(axis=1), axis=0)*100
w['pfn'] = w['LFN'] / w['Exprimés'] * 100

Régression au niveau 2 de la nomenclature CLC

Pour finir, on recalcule les niveau 1 et 2 de la nomenclature CLC sous forme de MultiIndex.


In [83]:
clc2 = [ (x[:2], x[:3], x) for x in pclc]
iclc2 = pd.MultiIndex.from_tuples(clc2)

w1 = pd.DataFrame(w[pclc].values, columns=iclc2, index=w.index)
X = w1.sum(level=1, axis=1)
y = w.pfn

# Fit regression model
results = sm.OLS(y, X).fit()

# Inspect the results
print results.summary()


                            OLS Regression Results                            
==============================================================================
Dep. Variable:                    pfn   R-squared:                       0.904
Model:                            OLS   Adj. R-squared:                  0.904
Method:                 Least Squares   F-statistic:                 2.292e+04
Date:                Wed, 30 Jul 2014   Prob (F-statistic):               0.00
Time:                        14:06:11   Log-Likelihood:            -1.3459e+05
No. Observations:               36535   AIC:                         2.692e+05
Df Residuals:                   36520   BIC:                         2.693e+05
Df Model:                          15                                         
==============================================================================
                 coef    std err          t      P>|t|      [95.0% Conf. Int.]
------------------------------------------------------------------------------
p11            0.2379      0.006     41.114      0.000         0.227     0.249
p12            0.3074      0.015     20.383      0.000         0.278     0.337
p13            0.7680      0.041     18.955      0.000         0.689     0.847
p14           -0.0283      0.032     -0.893      0.372        -0.090     0.034
p21            0.3560      0.001    285.627      0.000         0.354     0.358
p22            0.3510      0.005     74.882      0.000         0.342     0.360
p23            0.2994      0.002    132.408      0.000         0.295     0.304
p24            0.1683      0.003     56.846      0.000         0.163     0.174
p31            0.2908      0.002    146.672      0.000         0.287     0.295
p32            0.1811      0.005     34.272      0.000         0.171     0.191
p33            0.1843      0.014     12.774      0.000         0.156     0.213
p41            0.5511      0.039     13.987      0.000         0.474     0.628
p42            0.3071      0.041      7.521      0.000         0.227     0.387
p51            0.3707      0.021     17.311      0.000         0.329     0.413
p52            0.4955      0.044     11.355      0.000         0.410     0.581
==============================================================================
Omnibus:                      784.554   Durbin-Watson:                   1.488
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              954.168
Skew:                           0.299   Prob(JB):                    6.38e-208
Kurtosis:                       3.520   Cond. No.                         45.9
==============================================================================

Visualisation coefficients

La valeur des coefficients de la regression indique la propension de chaque type de sol à augmenter le vote FN. C'est la catégorie "mines, décharges et chantiers" qui arrive en tête, suivie des zones humides intérieures et des eaux maritimes, c'est-à-dire le littoral. Seule la présence d'espaces verts a un impact négatif.


In [84]:
lib = pd.read_csv('data/lib_clc2.csv', delimiter='\t', index_col=[0])
r = results.params

pos =  arange(len(r))
plt.figure(figsize=(14,8))
plt.yticks(arange(len(r)), lib.lib)
plt.barh(pos, r, align='center')
plt.show()